import * as THREE from "./threejs/three.module.js";
import * as ThreeComm from '../js/three-comm.js';
//1、周二 11:40  2、周三晚上不答疑 12：05  6：04

const DRAG_MESS_TYPES = ',BoxGeometry,BufferGeometry,';
const DRAG_MARKER_TYPES = ',SphereGeometry,';

//判断子字符串是否在当前字符串中
export function isContain(str,sub){
  if(null==str || typeof(str)=='undefined' || ''==str){
    return false;
  }
  if(null==sub || typeof(sub)=='undefined' || ''==sub){
    return false;
  }
  var sSub = ','+sub+',';
  var sStr = str;
  if(!sStr.startsWith(',')){
    sStr = ','+sStr;
  }
  if(!sStr.endsWith(',')){
    sStr += ',';
  }
  if(sStr.indexOf(sSub)<0){
    return false;
  }
  return true;
}
//判断当前模型是否为拖动标志物
export function isDragMarker(hMarker){
  var messType = ThreeComm.getMessType(hMarker);
  var bIsMarker= isContain(DRAG_MARKER_TYPES,messType);
  var dataType = ThreeComm.getMessUserDataType(hMarker);
  if('drag'!=dataType){
    return false;
  }
  return bIsMarker;
}
//判断当前模型是否为拖动目标
export function isDragMess(hMess){
  var messType = ThreeComm.getMessType(hMess);
  var bIsDrag  = isContain(DRAG_MESS_TYPES,messType);
  var dataType = ThreeComm.getMessUserDataType(hMess);
  if('drag'==dataType || ''==dataType){
    return false;
  }
  return bIsDrag;
}
//清空拖动模型的标志物
export function clearDragMarkers(hScene,hMess){
  if(ThreeComm.isEmpty(hScene) || ThreeComm.isEmpty(hMess)){
    return;
  }
  if(ThreeComm.isEmpty(hMess.children)){
    return;
  }
  var iSize = hMess.children.length;
  var hChild,userType,messType;
  for(var i=0;i<iSize;i++){
    hChild = hMess.children[i];
    if(ThreeComm.isEmpty(hChild)){
      continue;
    }
    userType = ThreeComm.getMessUserDataType(hChild);
    messType = ThreeComm.getMessType(hChild);
    if('drag'==userType || 'ArrowHelper'==messType){
      hChild.removeFromParent();
    }
    if('ArrowHelper'==messType){
      hScene.remove(hChild);
      hChild.dispose();
    }
  }
  console.log('clearDragMarker',hMess)
}
//创建选择的模型的各个面的中心点的拖动图标
export function createDragMarkers(hScene,hMess){
  if(ThreeComm.isEmpty(hScene) || ThreeComm.isEmpty(hMess)){
    return;
  }
  var messIdex = ThreeComm.getMessGeometryIndex(hMess);
  if(null==messIdex || typeof(messIdex)=="undefined"){
    return null;
  }
  var vertexs  = ThreeComm.getMessVertexs(hMess);
  if(null==vertexs || typeof(vertexs)=='undefined'){
    return null;
  }
  var idxArr = messIdex.array;
  if(ThreeComm.isEmpty(idxArr) || !(idxArr  instanceof Uint16Array)){
    return;
  }
  var iSize = idxArr.length;
  var faceSize = ThreeComm.accDiv(iSize,6);
  var facePoint;
  var dargMarker;
  var messCenter = getMessCenter(vertexs,idxArr);
  cleanDragMarkers();
  for(var faceIdx=0;faceIdx<faceSize;faceIdx++){
    facePoint = getCenterByFaceIdx(vertexs,idxArr,faceIdx);
    dargMarker = createDragMarker(hScene,hMess,messCenter,faceIdx,facePoint);
    hMess.add(dargMarker);
  }
}

//创建选择的模型的各个面的中心点的拖动图标
var dargMarkers = []
var dragRaycaster = null;
const dargGeometry = new THREE.SphereGeometry( 1, 32, 16 );
const dargMaterial = new THREE.MeshBasicMaterial( { color: 0xffff00 } );

export function getRaycasterProjectionPoint(hMarker,p0){
  if(ThreeComm.isEmpty(hMarker) || ThreeComm.isEmpty(p0)){
    console.log('getRaycasterProjectionPoint hMarker is null');
    return null;
  }
  var userData= ThreeComm.getMessUserData(hMarker);
  if(ThreeComm.isEmpty(userData)){
    console.log('getRaycasterProjectionPoint userData is null',hMarker);
    return 0;
  }

  var point   = hMarker.position;
  var points  = userData.points
  var nVector = userData.nVector;
  var center  = userData.center;
  var vCenter = ThreeComm.pointToVector3(center);
  var vPoint  = ThreeComm.pointToVector3(point);
  var vnVector= ThreeComm.pointToVector3(nVector);
 
  if(ThreeComm.isEmpty(center) || ThreeComm.isEmpty(nVector)){
    console.log('getRaycasterProjectionPoint nVector/center is null');
    return 0;
  }
  if(ThreeComm.isEmpty(dragRaycaster)){
    dragRaycaster = new THREE.Raycaster(vCenter, vnVector);
  }else{
    dragRaycaster.set(vCenter, vnVector);
  }
  var vP0 = ThreeComm.pointToVector3(p0);
  // 计算投影点 intersection现在是点在射线上的投影点
  var intersection = dragRaycaster.ray.at(point.projectOnVector(dragRaycaster.ray.direction).multiplyScalar(dragRaycaster.ray.direction.dot(vP0.normalize())).length(), new THREE.Vector3());
  return intersection;
}

//清空拖拉模型的分组或者是父亲
export function cleanDragMarkers(){
  var iSize = dargMarkers.length;
  var dargMarker;
  var hParent,messType;
  for(var i=0;i<iSize;i++){
    dargMarker = dargMarkers[i];
    if(null==dargMarker || typeof(dargMarker)=='undefined'){
      continue;
    }
    hParent = dargMarker.parent;
    messType = ThreeComm.getMessType(hParent);
    if(ThreeComm.isEmpty(messType) || 'Scene'==messType){
      continue;
    }
    dargMarker.removeFromParent();
  }
}


//创建标准物
export function getDragScaleByMarker(hScene,hMarker){
  if(ThreeComm.isEmpty(hScene) || ThreeComm.isEmpty(hMarker)){
    console.log('getDragScaleByMarker hScene is null');
    return 0;
  }
  var userData= ThreeComm.getMessUserData(hMarker);
  if(ThreeComm.isEmpty(userData)){
    console.log('getDragScaleByMarker userData is null',hMarker);
    return 0;
  }
  var point   = hMarker.position;
  var points  = userData.points
  if(ThreeComm.isEmpty(points)){
    return 0;
  }

  var faceDis = userData.faceDis;
  var curDis  = distanceToPlane(point,points[0],points[1],points[2]);
  var totalDis = ThreeComm.accAdd(faceDis,curDis);
  var result   = ThreeComm.accDiv(curDis,totalDis);
  return result;
}
var dragPlane = new THREE.Plane();
//计算点到三点构成的面的距离 http://www.yanhuangxueyuan.com/doc/Three.js/Line3RayPlane.html
export function distanceToPlane(p0,p1,p2,p3){
  var pv0 = ThreeComm.pointToVector3(p0);
  var pv1 = ThreeComm.pointToVector3(p1);
  var pv2 = ThreeComm.pointToVector3(p2);
  var pv3 = ThreeComm.pointToVector3(p3);
  //通过三个点定义一个平面
  dragPlane.setFromCoplanarPoints(pv1,pv2,pv3); 
  //计算中心点到本平面的垂直距离
  var result = dragPlane.distanceToPoint(pv0);
  return result;
}
//创建标准物
export function createDragMarker(hScene,hMess,messCenter,faceIdx,facePoint){
  if(ThreeComm.isEmpty(hScene) || ThreeComm.isEmpty(facePoint) || !ThreeComm.isNum(faceIdx)){
    return null;
  }
  var dragMarker;
  while(faceIdx>=dargMarkers.length){
    dragMarker =  new THREE.Mesh( dargGeometry, dargMaterial )
    dragMarker.visible = false;
    hScene.add(dragMarker);
    dargMarkers.push(dragMarker)
  }
  var center = facePoint.center;
  dragMarker = dargMarkers[faceIdx]
  dragMarker.visible = true;
  dragMarker.position.x = center.x;
  dragMarker.position.y = center.y;
  dragMarker.position.z = center.z;

  var points  = facePoint.points;
  var dis     = distanceToPlane(messCenter.center,points[0],points[1],points[2]);
  var faceDis = ThreeComm.accMul(dis,2);
  var faceDis = Math.abs(faceDis);

  var nVector = getNormalVector(points[0],points[1],points[2])
  var arrow   = new THREE.ArrowHelper(nVector,center,  8, 0xfff000);
  hMess.add(arrow);
  dragMarker.userData = {faceIdx:faceIdx,type:'drag',points:points,center:center,nVector:nVector,faceDis:faceDis}
  console.log('createDragMarker dragMarker=',dragMarker);
  return dragMarker;
}
export function getNormalVector(p1,p2,p3){
  if(!ThreeComm.isPoint(p1) || !ThreeComm.isPoint(p2) ||!ThreeComm.isPoint(p3)){
    return null;
  }
  var pv1 = ThreeComm.pointToVector3(p1);
  var pv2 = ThreeComm.pointToVector3(p2);
  var pv3 = ThreeComm.pointToVector3(p3);

  // 三个顶点构建两个向量，按照三角形顶点的顺序，构建1指向2的向量，2指向3的向量
  var a = pv2.clone().sub(pv1);
  var b = pv3.clone().sub(pv2);
  var c = a.clone().cross(b);
  c.normalize();//向量c归一化表示三角形法线方向
  return c;
}
export function getCenterByFaceIdx(vertexs,idxArr,faceIdx){
  if(!(idxArr  instanceof Uint16Array) || !(vertexs  instanceof Float32Array) || !ThreeComm.isNum(faceIdx)){
    console.log('getCenterByFaceIdx is null')
    return null;
  }
  var idx = ThreeComm.accMul(faceIdx,6);
  var iSizeIdx     = idxArr.length;
  var iSizeVertexs = vertexs.length;
  if(iSizeIdx-1>idx+6){
    iSizeIdx = idx+6;
  }
  var fIdx,vIdx;
  var x,y,z,sx=0,sy=0,sz=0,sIdx=0;
  var tmp = []
  var bIsExist ;
  for(var i= idx;i<iSizeIdx;i++){
    fIdx = idxArr[i];
    bIsExist = false;
    for(var j=0;j<tmp.length;j++){
      if(fIdx==tmp[j]){
        bIsExist = true;
        break;
      }
    }
    if(!bIsExist){
      tmp.push(fIdx);
    }
  }
  var points = [];
  iSizeIdx = tmp.length;
  for(var i= 0;i<iSizeIdx;i++){
    fIdx = tmp[i];
    vIdx = fIdx*3;
    if(vIdx+3>iSizeVertexs){
      continue;
    }
    x = vertexs[vIdx];
    y = vertexs[vIdx+1];
    z = vertexs[vIdx+2];
    sx = ThreeComm.accAdd(sx,x);
    sy = ThreeComm.accAdd(sy,y);
    sz = ThreeComm.accAdd(sz,z);
    sIdx ++;
    points.push({x:x,y:y,z:z});
  }
  if(sIdx<1){
    return null;
  }
  sx = ThreeComm.accDiv(sx,sIdx);
  sy = ThreeComm.accDiv(sy,sIdx);
  sz = ThreeComm.accDiv(sz,sIdx);
  var result ={center:{x:sx,y:sy,z:sz},points:points} ;
  return result;
}

export function existInArray(obj,arr){
  if(ThreeComm.isEmpty(arr)){
    return false;
  }
  var iSize = arr.length;
  var val;
  for(var i=0;i<iSize;i++){
    val = arr[i];
    if(val==obj){
      return true;
    }
  }
  return false;
}
export function getMessCenter(vertexs,idxArr){
  if(!(idxArr  instanceof Uint16Array) || !(vertexs  instanceof Float32Array)){
    console.log('getCenterByFaceIdx is null')
    return null;
  }
  var iSizeIdx     = idxArr.length;
  var iSizeVertexs = vertexs.length;
  
  var vIdx;
  var x,y,z,sx=0,sy=0,sz=0,sIdx=0;
  var tmp = []
  var bIsExist ;
  for(var i= 0;i<iSizeIdx;i++){
    vIdx     = idxArr[i];
    bIsExist = existInArray(vIdx,tmp);
    if(!bIsExist){
      tmp.push(vIdx);
    }
  }
  var sIdx   = 0;
  var points = [];
  iSizeIdx = tmp.length;
  for(var i= 0;i<iSizeIdx;i++){
    vIdx = tmp[i];
    vIdx = vIdx*3;
    if(vIdx+3>iSizeVertexs){
      continue;
    }
    x = vertexs[vIdx];
    y = vertexs[vIdx+1];
    z = vertexs[vIdx+2];
    sx = ThreeComm.accAdd(sx,x);
    sy = ThreeComm.accAdd(sy,y);
    sz = ThreeComm.accAdd(sz,z);
    sIdx ++;
    points.push({x:x,y:y,z:z});
  }
  if(sIdx<1){
    return null;
  }
  sx = ThreeComm.accDiv(sx,sIdx);
  sy = ThreeComm.accDiv(sy,sIdx);
  sz = ThreeComm.accDiv(sz,sIdx);
  var result ={center:{x:sx,y:sy,z:sz},points:points} ;
  return result;
}